#include <iostream>
#include <pcap.h>
#include <stdint.h>
#include <stdio.h>

// 定义IP头部结构体
struct IPHeader
{
    uint8_t version_and_length; // 版本和头部长度
    uint8_t tos;                // 服务类型
    uint16_t total_length;      // 总长度
    uint16_t id;                // 标识
    uint16_t flags_and_offset;  // 标志和片偏移
    uint8_t ttl;                // 生存时间
    uint8_t protocol;           // 协议
    uint16_t checksum;          // 校验和
    uint32_t source;            // 源地址
    uint32_t destination;       // 目的地址
};

// 网际校验和计算函数
uint16_t calculate_checksum(const uint16_t *data, size_t length)
{
    uint32_t sum = 0;
    // 累加每个16位数据块
    while (length > 1)
    {
        sum += *data++;
        length -= 2;
    }

    // 如果有一个剩余字节，加入到和中
    if (length == 1)
    {
        sum += *(uint8_t *)data;
    }

    // 将高16位加到低16位
    while (sum >> 16)
    {
        sum = (sum & 0xFFFF) + (sum >> 16);
    }

    // 取反操作
    return ~sum;
}

// 解析和处理 pcap 文件中的每个包
void process_packet(const uint8_t *packet, size_t packet_len)
{
    // 获取IP头部
    IPHeader *ip_header = (IPHeader *)packet;

    // 提取IP头部信息（简化版，假设没有选项字段）
    uint16_t ip_checksum = calculate_checksum((uint16_t *)packet, sizeof(IPHeader));

    std::cout << "Calculated IP Checksum: 0x" << std::hex << ip_checksum << std::endl;
}

// 读取并处理 pcap 文件
void process_pcap_file(const char *filename)
{
    pcap_t *handle;                // pcap 文件句柄
    char errbuf[PCAP_ERRBUF_SIZE]; // 错误缓冲区

    // 打开 pcap 文件
    handle = pcap_open_offline(filename, errbuf);
    if (handle == NULL)
    {
        std::cerr << "Error opening pcap file: " << errbuf << std::endl;
        return;
    }

    // 读取并处理每个数据包
    struct pcap_pkthdr header; // 数据包头部
    const uint8_t *packet;     // 数据包内容

    while ((packet = pcap_next(handle, &header)) != NULL)
    {
        std::cout << "Processing packet with length " << header.len << " bytes" << std::endl;
        process_packet(packet, header.len);
    }

    // 关闭 pcap 文件
    pcap_close(handle);
}

int main()
{
    // 输入你的 pcap 文件路径
    const char *pcap_filename = "test.pcapng";
    process_pcap_file(pcap_filename);
    return 0;
}
